
#include <BFile>
#include <BFolder>
#include <BSystem>
#include "member_BStyleDocument.h"
#include "member_BWidget.h"
#include "member_BIcon.h"
#include "IGlobal.h"

using namespace BWE;

member_BStyleDocument::member_BStyleDocument(BStyleDocument* styleDocument)
{
	boss = styleDocument;
	message = new BString();
	lineNumber = 1;
	linePos = 0;
}
member_BStyleDocument::~member_BStyleDocument()
{

}

void member_BStyleDocument::read(BStyle* style, const BString& text, int& pos)
{
	BString temp;
	BString comment;
	while (pos < text.size())
	{
		if (text[pos] == '\n' && pos > linePos)
		{
			lineNumber++;
			linePos = pos;
		}
		if (text[pos] == '\r' || text[pos] == '\t' || text[pos] == '\n')
		{
			pos++;
			continue;
		}
		if (text[pos] == '/' && text(pos + 1) == '*')
		{
			readComment(text, ++pos, comment);
			continue;
		}
		if (text[pos] == '/' && text(pos + 1) == '/')
		{
			readComment(text, ++pos, comment);
			continue;
		}
		char code = text[pos];
		if (code == '}')
		{
			pos++;
			break;
		}
		if (code == ';')
		{
			readDesc(temp, style);
			temp.reset();
			pos++;
			continue;
		}
		if (code == '{')
		{
			pos++;
			BString str;
			while (temp.contain(','))
			{
				int end = temp.find(',');
				temp.substr(str, 0, end);
				temp.remove(0, end + 1);
				str.trimmed();
				BStyle* child = findChild(str, style);
				int begin = pos;
				read(child, text, pos);
				pos = begin;
			}
			temp.trimmed();
			BStyle* child = findChild(temp, style);
			read(child, text, pos);
			temp.reset();
			continue;
		}
		temp.append(code);
		pos++;
	}
	if (temp.size() > 1)
	{
		readDesc(temp, style);
		temp.reset();
	}
}
void member_BStyleDocument::write(const BStyle* style, BString& text, int level)
{
	if (style_member(style)->valueMap.size())
	{
		for (auto it = style_member(style)->valueMap.begin(); it.valid(); ++it)
		{
			text.append('\t', level);
			assemble(text, it.key(), it.value());
			text << '\n';
		}
	}
	if (style_member(style)->colorMap.size())
	{
		BString value;
		for (auto it = style_member(style)->colorMap.begin(); it.valid(); ++it)
		{
			text.append('\t', level);
			assemble(text, it.key(), it.value());
			text << '\n';
		}
	}
	if (style_member(style)->imageMap.size())
	{
		for (auto it = style_member(style)->imageMap.begin(); it.valid(); ++it)
		{
			text.append('\t', level);
			assemble(text, it.key(), it.value());
			text << '\n';
		}
	}
	if (style_member(style)->iconMap.size())
	{
		for (auto it = style_member(style)->iconMap.begin(); it.valid(); ++it)
		{
			text.append('\t', level);
			assemble(text, it.key(), it.value());
			text << '\n';
		}
	}

	if (style_member(style)->namedColorMap.size())
	{
		for (auto it = style_member(style)->namedColorMap.begin(); it.valid(); ++it)
		{
			const BString& name = it.key();
			const BColor& color = it.value();
			text.append('\t', level);
			text << "*color" << name << ':' << color.r() << ", " << color.g() << ", " << color.b();
			if (color.a() < 255)
				text << ", " << color.a();
			text << ";\n";
		}
	}
	if (style_member(style)->namedImageMap.size())
	{
		for (auto it = style_member(style)->namedImageMap.begin(); it.valid(); ++it)
		{
			const BString& name = it.key();
			const BImage* image = it.value();
			text.append('\t', level);
			text << "*image: " << name << ':' << image->fileName() << ";\n";
		}
	}
	if (style_member(style)->namedIconMap.size())
	{
		for (auto it = style_member(style)->namedIconMap.begin(); it.valid(); ++it)
		{
			const BString& name = it.key();
			const BIcon* icon = it.value();
			text.append('\t', level);
			text << "*icon: " << name << ':' << icon->name() << ";\n";
		}
	}

	if (style_member(style)->transMap.size())
	{
		for (auto it = style_member(style)->transMap.begin(); it.valid(); ++it)
		{
			const BString& name = it.key();
			const BString& word = it.value();
			text.append('\t', level);
			text << "*trans: " << name << ':' << word << ";\n";
		}
	}
	if (style_member(style)->wordMap.size())
	{
		for (auto it = style_member(style)->wordMap.begin(); it.valid(); ++it)
		{
			const BString& name = it.key();
			const BString& word = it.value();
			text.append('\t', level);
			text << "*word: " << name << ':' << word << ";\n";
		}
	}
	if (style_member(style)->textMap.size())
	{
		for (auto it = style_member(style)->textMap.begin(); it.valid(); ++it)
		{
			const BString& name = it.key();
			const BString& word = it.value();
			text.append('\t', level);
			text << "*text: " << name << ':' << word << ";\n";
		}
	}

	if (style_member(style)->annexes.size())
	{
		for (int i = 0; i < style_member(style)->annexes.size(); i++)
		{
			const BStyle* annex = style_member(style)->annexes[i];
			text.append('\t', level);
			text << ':';
			if (!annex->heritable())
				text << '.';
			text << annex->type();
			if (annex->name().size())
				text << '#' << annex->name();
			text << "{\n";
			write(annex, text, level + 1);
			text.append('\t', level);
			text << "}\n";
		}
	}
	if (style_member(style)->children.size())
	{
		for (int i = 0; i < style_member(style)->children.size(); i++)
		{
			const BStyle* child = style_member(style)->children[i];
			text.append('\t', level);
			if (!child->heritable())
				text << '.';
			text << child->type();
			if (child->name().size())
				text << '#' << child->name();
			text << "{\n";
			write(child, text, level + 1);
			text.append('\t', level);
			text << "}\n";
		}
	}
}

BString& member_BStyleDocument::errorMessage()
{
	error = true;
	BString& text = message.fill<BString>();
	if (text.size())
		text << '\n';
	text << "\tError [" << lineNumber << "] : ";
	return text;
}
BString& member_BStyleDocument::warningMessage()
{
	BString& text = message.fill<BString>();
	if (text.size())
		text << '\n';
	text << "\tWarning [" << lineNumber << "] : ";
	return text;
}

bool member_BStyleDocument::readComment(const BString& text, int& pos, BString& comment)
{
	comment.reset();
	if (text[pos] == '*')
	{
		while (++pos < text.size())
		{
			char c = text[pos];
			if (c == '\n' && pos > linePos)
			{
				lineNumber++;
				linePos = pos;
			}
			else if (c == '*' && text(pos + 1) == '/')
			{
				pos += 2;
				return true;
			}
			comment << c;
		}
		return pos == text.size();
	}
	if (text[pos] == '/')
	{
		while (++pos < text.size())
		{
			char c = text[pos];
			if (c == '\n')
			{
				pos++;
				lineNumber++;
				linePos = pos;
				return true;
			}
			comment << c;
		}
		return pos == text.size();
	}
	return false;
}
BStyle* member_BStyleDocument::findChild(BString& text, BStyle* style)
{
	if (text.endWith('>') || text.endWith(':'))
	{
		BCode last = text.last();
		errorMessage() << "tails '" << last << "' will be ignored : " << text;
		while (text.endWith(last))
		{
			text -= last;
			text.trimmed();
		}
	}
	text.replace('>', " >", 1);
	text.simplify();
	text.replace("> ", '>');
	text.replace(": ", ':');
	text.trimmed();
	int end = text.find(' ');
	if (end < text.size())
	{
		BString str;
		text.substr(str, 0, end);
		BStyle* child = addStyle(str, style);
		int pos = end + 1;
		while (child && pos < text.size())
		{
			end = text.find(' ', pos);
			text.substr(str, pos, end);
			child = addStyle(str, child);
			pos = end + 1;
		}
		return child;
	}
	BStyle* child = addStyle(text, style);
	return child;
}
BStyle* member_BStyleDocument::addStyle(BString& text, BStyle* parent)
{
	text.simplify();
	text.trimmed();
	if (text.beginWith(':'))
	{
		BStyle* style = addAnnex(text, 1, parent);
		return style;
	}
	int stop = text.find(':');
	BString type;
	BString name;
	int name_pos = text.find('#', 0, stop);
	text.substr(type, 0, name_pos);
	type.simplify();
	type.trimmed();
	if (name_pos < stop)
	{
		text.substr(name, name_pos + 1, stop);
		name.simplify();
		name.trimmed();
	}
	bool heritable = true;
	if (type.beginWith('.'))
	{
		type.remove(0);
		heritable = false;
	}
	bool descendant = true;
	if (type.beginWith('>'))
	{
		type.remove(0);
		descendant = false;
	}
	BStyle* style = parent->child(type, name);
	if (style == 0 || style_member(style)->heritable != heritable || style_member(style)->descendant != descendant)
	{
		style = new BStyle(name);
		style_member(style)->type = type;
		style_member(style)->heritable = heritable;
		style_member(style)->descendant = descendant;
		parent->addChild(style);
	}
	else
	{
		style->lower();
	}
	if (stop < text.size())
	{
		style = addAnnex(text, stop + 1, style);
	}
	return style;
}
BStyle* member_BStyleDocument::addAnnex(BString& text, int pos, BStyle* style)
{
	BString name;
	int stop = text.find(':', pos);
	text.substr(name, pos, stop);
	name.simplify();
	name.trimmed();
	BStyle* annex = style->annex(name);
	if (annex == 0)
	{
		annex = new BStyle();
		annex->setName(name);
		style->addAnnex(annex);
	}
	if (stop < text.size())
	{
		annex = addAnnex(text, stop + 1, annex);
	}
	return annex;
}

void member_BStyleDocument::readDesc(BString& text, BStyle* style)
{
	text.simplify();
	text.trimmed();
	if (text.size())
	{
		int sem_pos = text.find(':');
		if (sem_pos < text.size())
		{
			BString sign;
			text.substr(sign, 0, sem_pos);
			sign.simplify();
			sign.trimmed();
			BString value;
			text.substr(value, sem_pos + 1, text.size());
			value.simplify();
			value.trimmed();
			analysis(sign, value, style);
		}
		else if (text.beginWith("@import"))
		{
			text.remove(0, 8);
			text.trimmed();
			text.removeHead('\"');
			text.removeTail('\"');
			text.prepend('/');
			text.prepend(path);
			BFile file(text);
			if (!file.open(IO_ReadText))
			{
				errorMessage() << "open file failed : " << text;
				return;
			}
			BString backupPath = path;
			int backupLineNumber = lineNumber;
			int backupLinePos = linePos;
			if (BStyle* annex = new BStyle())
			{
				path = text.path();
				lineNumber = 1;
				linePos = 0;
				file.read(text);
				int pos = 0;
				read(style, text, pos);
				style->addChild(annex);
			}
			path = backupPath;
			lineNumber = backupLineNumber;
			linePos = backupLinePos;
		}
		else
		{
			text.simplify();
			text.trimmed();
			BString value;
			analysis(text, value, style);
		}
	}
}
void member_BStyleDocument::analysis(BString& sign, BString& value, BStyle* style)
{
	if (sign.beginWith("background"))
	{
		analysisBackground(style, sign, value);
		return;
	}
	if (sign.beginWith("foreground"))
	{
		analysisForeground(style, sign, value);
		return;
	}
	if (sign.beginWith("border"))
	{
		analysisBorder(style, sign, value);
		return;
	}
	if (sign.beginWith("perch"))
	{
		analysisPerch(style, sign, value);
		return;
	}
	if (sign.beginWith("margin"))
	{
		analysisMargin(style, sign, value);
		return;
	}
	if (sign.beginWith("text"))
	{
		analysisText(style, sign, value);
		return;
	}
	if (sign.beginWith("font"))
	{
		analysisFont(style, sign, value);
		return;
	}
	if (sign.beginWith("title"))
	{
		analysisTitle(style, sign, value);
		return;
	}
	if (sign.beginWith("image"))
	{
		analysisImage(style, sign, value);
		return;
	}
	if (sign.beginWith("icon"))
	{
		analysisIcon(style, sign, value);
		return;
	}
	if (sign.beginWith("area"))
	{
		analysisArea(style, sign, value);
		return;
	}
	if (sign.beginWith("scroll"))
	{
		analysisScroll(style, sign, value);
		return;
	}
	if (sign.beginWith("spread"))
	{
		analysisSpread(style, sign, value);
		return;
	}
	if (sign.beginWith("chunk"))
	{
		analysisChunk(style, sign, value);
		return;
	}
	if (sign.beginWith("groove"))
	{
		analysisGroove(style, sign, value);
		return;
	}
	if (sign.beginWith("handle"))
	{
		analysisHandle(style, sign, value);
		return;
	}
	if (sign.beginWith("selection"))
	{
		analysisSelection(style, sign, value);
		return;
	}
	if (sign.beginWith("indicator"))
	{
		analysisIndicator(style, sign, value);
		return;
	}
	if (sign.beginWith("arrow"))
	{
		analysisArrow(style, sign, value);
		return;
	}
	if (sign.beginWith("grid"))
	{
		analysisGridLine(style, sign, value);
		return;
	}
	if (sign.beginWith("fixed"))
	{
		analysisFixed(style, sign, value);
		return;
	}
	if (sign.beginWith("min"))
	{
		analysisMin(style, sign, value);
		return;
	}
	if (sign.beginWith("max"))
	{
		analysisMax(style, sign, value);
		return;
	}
	if (sign.beginWith("radius"))
	{
		analysisRadius(style, sign, value);
		return;
	}

	if (sign == "visible")
	{
		if (!style_member(style)->setBoolValue(Value_Visible, value))
			errorMessage() << "invalid bool desc : " << value;
		return;
	}
	if (sign == "graph")
	{
		if (!style_member(style)->setGraphValue(Value_Graph, value))
			errorMessage() << "invalid sign value : " << sign;
		return;
	}

	if (sign == "size")
	{
		if (value.contain(','))
		{
			BStringArray words = value.split(',');
			if (!style_member(style)->setIntValue(Value_Width, words[0]))
				errorMessage() << "invalid size value : " << value;
			if (!style_member(style)->setIntValue(Value_Height, words[1]))
				errorMessage() << "invalid size value : " << value;
		}
		else
		{
			if (!style_member(style)->setIntValue(Value_Width, value))
				errorMessage() << "invalid size value : " << value;
			if (!style_member(style)->setIntValue(Value_Height, value))
				errorMessage() << "invalid size value : " << value;
		}
		return;
	}
	if (sign == "width")
	{
		int width = value.toInt();
		style_member(style)->valueMap[Value_Width] = width;
		return;
	}
	if (sign == "height")
	{
		int height = value.toInt();
		style_member(style)->valueMap[Value_Height] = height;
		return;
	}

	if (sign == "form")
	{
		if (!style_member(style)->setFormValue(Value_Form, value))
			errorMessage() << "invalid form value : " << value;
		return;
	}
	if (sign == "align")
	{
		if (!style_member(style)->setAlignValue(Value_Align, value))
			errorMessage() << "invalid align value : " << value;
		return;
	}

	if (sign == "spacing")
	{
		if (!style_member(style)->setIntValue(Value_Spacing, value))
			errorMessage() << "invalid spacing value : " << value;
		return;
	}
	if (sign == "ver-spacing")
	{
		if (!style_member(style)->setIntValue(Value_VerSpacing, value))
			errorMessage() << "invalid vertical spacing value : " << value;
		return;
	}
	if (sign == "hor-spacing")
	{
		if (!style_member(style)->setIntValue(Value_HorSpacing, value))
			errorMessage() << "invalid horizontal spacing value : " << value;
		return;
	}
	if (sign == "item-spacing")
	{
		if (!style_member(style)->setIntValue(Value_ItemSpacing, value))
			errorMessage() << "invalid item spacing value : " << value;
		return;
	}

	if (sign == "color")
	{
		BColor color;
		if (readColor(value, color))
			style_member(style)->valueMap[Value_Color] = color;
		return;
	}
	if (sign == "tips")
	{
		style_member(style)->valueMap[Value_Tips] = value;
		return;
	}
	if (sign == "frameless")
	{
		if (!style_member(style)->setBoolValue(Value_FrameLess, value))
			errorMessage() << "invalid bool desc : " << value;
		return;
	}
	if (sign == "samples")
	{
		if (!style_member(style)->setIntValue(Value_Samples, value))
			errorMessage() << "invalid sample value : " << value;
		return;
	}
	if (sign == "offset")
	{
		if (!style_member(style)->setPointValue(Value_Offset, value))
			errorMessage() << "invalid offset value : " << value;
		return;
	}
	if (sign == "flat")
	{
		if (!style_member(style)->setBoolValue(Value_Flat, value))
			errorMessage() << "invalid bool desc : " << value;
		return;
	}
	if (sign == "wired")
	{
		if (!style_member(style)->setBoolValue(Value_Wired, value))
			errorMessage() << "invalid bool desc : " << value;
		return;
	}
	if (sign == "indent")
	{
		if (!style_member(style)->setIntValue(Value_Indent, value))
			errorMessage() << "invalid indent value : " << value;
		return;
	}
	if (sign == "format")
	{
		value.replace("\\:", ':');
		value.replace("\\s", ' ');
		value.replace("\\t", '\t');
		value.replace("\\n", '\n');
		style_member(style)->valueMap[Value_Format] = value;
		return;
	}
	if (sign == "translatable")
	{
		if (!style_member(style)->setBoolValue(Value_Translatable, value))
			errorMessage() << "invalid bool value : " << value;
		return;
	}
	if (sign == "orientation")
	{
		if (!style_member(style)->setOrientation(Value_Orientation, value))
			errorMessage() << "invalid orientation value : " << value;
		return;
	}

	if (sign.beginWith("line"))
	{
		analysisLine(style, sign, value);
		return;
	}
	if (sign.beginWith("wire"))
	{
		analysisWire(style, sign, value);
		return;
	}

	if (sign == "policy")
	{
		if (!style_member(style)->setPolicyValue(Value_Policy, value))
			errorMessage() << "invalid policy value : " << value;
		return;
	}
	if (sign == "width-policy")
	{
		if (!style_member(style)->setPolicyValue(Value_Width_Policy, value))
			errorMessage() << "invalid policy value : " << value;
		return;
	}
	if (sign == "height-policy")
	{
		if (!style_member(style)->setPolicyValue(Value_Height_Policy, value))
			errorMessage() << "invalid policy value : " << value;
		return;
	}
	if (sign == "size-policy")
	{
		if (value.contain(','))
		{
			value.compact();
			BStringArray words;
			if (2 == value.split(words, ','))
			{
				if (!style_member(style)->setPolicyValue(Value_Width_Policy, words[0]))
					errorMessage() << "invalid policy value : " << value;
				if (!style_member(style)->setPolicyValue(Value_Height_Policy, words[1]))
					errorMessage() << "invalid policy value : " << value;
			}
			return;
		}
		if (!style_member(style)->setPolicyValue(Value_Width_Policy, value))
			errorMessage() << "invalid policy value : " << value;
		if (!style_member(style)->setPolicyValue(Value_Height_Policy, value))
			errorMessage() << "invalid policy value : " << value;
		return;
	}

	if (sign == "*value")
	{
		resourceValue(style, sign, value);
		return;
	}
	if (sign == "*color")
	{
		resourceColor(style, sign, value);
		return;
	}
	if (sign == "*image")
	{
		resourceImage(style, sign, value);
		return;
	}
	if (sign == "*icon")
	{
		resourceIcon(style, sign, value);
		return;
	}
	if (sign == "*trans")
	{
		resourceTrans(style, sign, value);
		return;
	}
	if (sign == "*word")
	{
		resourceWord(style, sign, value);
		return;
	}
	if (sign == "*text")
	{
		resourceText(style, sign, value);
		return;
	}

	if (sign == "style")
	{
		BColor color;
		if (readColor(value, color))
			style_member(style)->init(color);
		return;
	}
	if (sign == "unset")
	{
		if (value.empty())
			value = "all";
		bool valid = (value == "all"
			|| value == "values"
			|| value == "colors"
			|| value == "images"
			|| value == "icons"
			|| value == "trans"
			|| value == "words"
			|| value == "texts");
		if (valid)
			style_member(style)->unset = value;
		else
			errorMessage() << "clear context is unknown : " << value;
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}

void member_BStyleDocument::analysisTitle(BStyle* style, BString& sign, BString& value)
{
	if (sign == "title" || sign == "title-text")
	{
		const BString& title = value;
		style_member(style)->valueMap[Value_Title] = title;
		return;
	}

	if (sign.beginWith("title-color"))
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Title, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Title, state, color);
		}
		return;
	}
	if (sign == "title-image")
	{
		if (assignMultiImage(style, Image_Title, value))
			return;
		if (BImage* image = this->readImage(value))
		{
			State state = StringToState(sign);
			style->setImage(Image_Title, state, image);
		}
		return;
	}
	if (sign.contain("title-image"))
	{
		State state = StringToState(sign);
		if (BImage* image = this->readImage(value))
			style_member(style)->imageMap[Image_Title + state] = image;
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisText(BStyle* style, BString& sign, BString& value)
{
	if (sign == "text")
	{
		BString& text = value;
		text.replace("\\:", ':');
		text.replace("\\s", ' ');
		text.replace("\\t", '\t');
		text.replace("\\n", '\n');
		style_member(style)->valueMap[Value_Text] = text;
		return;
	}

	if (sign.beginWith("text-color"))
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Text, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Text, state, color);
		}
		return;
	}

	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisBackground(BStyle* style, BString& sign, BString& value)
{
	if (sign.beginWith("background-image"))
	{
		if (assignMultiImage(style, Image_Background, value))
			return;
		BImage* image = this->readImage(value);
		State state = StringToState(sign);
		style->setImage(Image_Background, state, image);
		return;
	}

	State state = StringToState(sign);
	if (value == "unset")
	{
		style->removeColor(Color_Background, state);
		return;
	}
	sign.remove("-color");
	BColor color;
	if (readColor(value, color))
	{
		style->setColor(Color_Background, state, color);
	}
}
void member_BStyleDocument::analysisForeground(BStyle* style, BString& sign, BString& value)
{
	if (sign.beginWith("foreground-image"))
	{
		if (BImage* image = this->readImage(value))
		{
			State state = StringToState(sign);
			style->setImage(Image_Foreground, state, image);
		}
		return;
	}

	State state = StringToState(sign);
	if (value == "unset")
	{
		style->removeColor(Color_Foreground, state);
		return;
	}
	sign.remove("-color");
	BColor color;
	if (readColor(value, color))
	{
		style->setColor(Color_Foreground, state, color);
	}
}
void member_BStyleDocument::analysisBorder(BStyle* style, BString& sign, BString& value)
{
	if (sign == "border")
	{
		int pos = value.find(',');
		if (pos < value.size())
		{
			if (!value.isNumber())
			{
				errorMessage() << "" << sign << " : invalid border desc.";
				return;
			}
			style_member(style)->setIntValue(Value_Border, value);
			value.remove(0, pos + 1);
			State state = StringToState(sign);
			BColor color;
			if (readColor(value, color))
			{
				style->setColor(Color_Border, state, color);
			}
			return;
		}
		style_member(style)->setIntValue(Value_Border, value);
		return;
	}
	if (sign == "border-width" || sign == "border-size")
	{
		style_member(style)->setIntValue(Value_Border, value);
		return;
	}
	if (sign.beginWith("border-radius"))
	{
		sign.remove("border-");
		analysisRadius(style, sign, value);
		return;
	}

	if (sign.beginWith("border-color"))
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Border, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Border, state, color);
		}
		return;
	}

	if (sign.beginWith("border-image"))
	{
		if (assignMultiImage(style, Image_Border, value))
			return;
		if (BImage* image = this->readImage(value))
		{
			State state = StringToState(sign);
			style->setImage(Image_Border, state, image);
		}
		return;
	}

	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisPerch(BStyle* style, BString& sign, BString& value)
{
	if (sign == "perch")
	{
		if (value.contain(','))
		{
			value.compact();
			BStringArray words;
			value.split(words, ',');
			if (words.size() == 4)
			{
				style_member(style)->setIntValue(Value_Perch_Left, words[0]);
				style_member(style)->setIntValue(Value_Perch_Top, words[1]);
				style_member(style)->setIntValue(Value_Perch_Right, words[2]);
				style_member(style)->setIntValue(Value_Perch_Bottom, words[3]);
				return;
			}
			errorMessage() << "perch argument count should be 4 : " << value;
			return;
		}
		style_member(style)->setIntValue(Value_Perch_Left, value);
		style_member(style)->setIntValue(Value_Perch_Top, value);
		style_member(style)->setIntValue(Value_Perch_Right, value);
		style_member(style)->setIntValue(Value_Perch_Bottom, value);
		return;
	}
	if (sign == "perch-left")
	{
		style_member(style)->setIntValue(Value_Perch_Left, value);
		return;
	}
	if (sign == "perch-right")
	{
		style_member(style)->setIntValue(Value_Perch_Right, value);
		return;
	}
	if (sign == "perch-top")
	{
		style_member(style)->setIntValue(Value_Perch_Top, value);
		return;
	}
	if (sign == "perch-bottom")
	{
		style_member(style)->setIntValue(Value_Perch_Bottom, value);
		return;
	}

	if (sign.beginWith("perch-color"))
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Perch, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Perch, state, color);
		}
		return;
	}

	if (sign.beginWith("perch-image"))
	{
		if (assignMultiImage(style, Image_Perch, value))
			return;
		BImage* image = this->readImage(value);
		if (!image)
			return;
		State state = StringToState(sign);
		style->setImage(Image_Perch, state, image);
		return;
	}

	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisMargin(BStyle* style, BString& sign, BString& value)
{
	if (sign == "margin")
	{
		if (value.contain(','))
		{
			value.compact();
			BStringArray words;
			value.split(words, ',');
			if (words.size() == 4)
			{
				style_member(style)->setIntValue(Value_Margin_Left, words[0]);
				style_member(style)->setIntValue(Value_Margin_Top, words[1]);
				style_member(style)->setIntValue(Value_Margin_Right, words[2]);
				style_member(style)->setIntValue(Value_Margin_Bottom, words[3]);
				return;
			}
			if (words.size() == 2)
			{
				style_member(style)->setIntValue(Value_Margin_Left, words[0]);
				style_member(style)->setIntValue(Value_Margin_Top, words[1]);
				style_member(style)->setIntValue(Value_Margin_Right, words[0]);
				style_member(style)->setIntValue(Value_Margin_Bottom, words[1]);
				return;
			}
			errorMessage() << "margin argument count should be 1 or 2 or 4 : " << value;
			return;
		}
		style_member(style)->setIntValue(Value_Margin_Left, value);
		style_member(style)->setIntValue(Value_Margin_Top, value);
		style_member(style)->setIntValue(Value_Margin_Right, value);
		style_member(style)->setIntValue(Value_Margin_Bottom, value);
		return;
	}
	if (sign == "margin-left")
	{
		style_member(style)->setIntValue(Value_Margin_Left, value);
		return;
	}
	if (sign == "margin-right")
	{
		style_member(style)->setIntValue(Value_Margin_Right, value);
		return;
	}
	if (sign == "margin-top")
	{
		style_member(style)->setIntValue(Value_Margin_Top, value);
		return;
	}
	if (sign == "margin-bottom")
	{
		style_member(style)->setIntValue(Value_Margin_Bottom, value);
		return;
	}

	if (sign.beginWith("margin-color"))
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Margin, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Margin, state, color);
		}
		return;
	}

	if (sign.beginWith("margin-image"))
	{
		if (assignMultiImage(style, Image_Margin, value))
			return;
		BImage* image = this->readImage(value);
		if (!image)
			return;
		State state = StringToState(sign);
		style->setImage(Image_Margin, state, image);
		return;
	}

	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisRadius(BStyle* style, BString& sign, BString& value)
{
	if (sign == "radius")
	{
		if (value.contain(','))
		{
			value.compact();
			BStringArray words;
			value.split(words, ',');
			if (words.size() == 4)
			{
				style_member(style)->setSizeValue(Value_Radius_Left_Top, words[0]);
				style_member(style)->setSizeValue(Value_Radius_Right_Top, words[1]);
				style_member(style)->setSizeValue(Value_Radius_Right_Bottom, words[2]);
				style_member(style)->setSizeValue(Value_Radius_Left_Bottom, words[3]);
				return;
			}
			if (words.size() == 2)
			{
				int width = words[0].toInt();
				int height = words[1].toInt();
				style_member(style)->valueMap[Value_Radius_Left_Top] = BSize(width, height);
				style_member(style)->valueMap[Value_Radius_Right_Top] = BSize(width, height);
				style_member(style)->valueMap[Value_Radius_Right_Bottom] = BSize(width, height);
				style_member(style)->valueMap[Value_Radius_Left_Bottom] = BSize(width, height);
				return;
			}
			errorMessage() << "radius argument count should be 4 : " << value;
			return;
		}
		style_member(style)->setSizeValue(Value_Radius_Left_Top, value);
		style_member(style)->setSizeValue(Value_Radius_Right_Top, value);
		style_member(style)->setSizeValue(Value_Radius_Right_Bottom, value);
		style_member(style)->setSizeValue(Value_Radius_Left_Bottom, value);
		return;
	}
	if (sign == "radius-left-top")
	{
		if (!style_member(style)->setSizeValue(Value_Radius_Left_Top, value))
			errorMessage() << "radius invalid radius value : " << value;
		return;
	}
	if (sign == "radius-right-top")
	{
		if (!style_member(style)->setSizeValue(Value_Radius_Right_Top, value))
			errorMessage() << "radius invalid radius value : " << value;
		return;
	}
	if (sign == "radius-right-bottom")
	{
		if (!style_member(style)->setSizeValue(Value_Radius_Right_Bottom, value))
			errorMessage() << "radius invalid radius value : " << value;
		return;
	}
	if (sign == "radius-left-bottom")
	{
		if (!style_member(style)->setSizeValue(Value_Radius_Left_Bottom, value))
			errorMessage() << "radius invalid radius value : " << value;
		return;
	}

	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisFont(BStyle* style, BString& sign, BString& value)
{
	if (sign == "font")
	{
		BStringArray words;
		if (0 == value.split(words, ','))
			return;
		BFontHolder font = new BFont(words[0]);
		if (font->empty())
		{
			errorMessage() << "font initialized failed : " << value;
			return;
		}
		for (int i = 0; i < words.size(); i++)
			words[i].trimmed();
		style_member(style)->valueMap[Value_Font] = font;
		if (words(1).isNumber())
			font->setSize(words[1].toInt());
		if (words.contain("bold"))
			font->setBold(true);
		if (words.contain("italic"))
			font->setItalic(true);
		if (words.contain("mono") || words.contain("monospace"))
			font->setMonospace(true);
		return;
	}
	if (sign == "font-family")
	{
		if (value.empty())
			return;
		BFontHolder font = new BFont(value);
		if (font->empty())
		{
			errorMessage() << "font initialized failed : " << value;
			return;
		}
		style_member(style)->valueMap[Value_Font] = font;
		return;
	}
	if (sign == "font-size")
	{
		int size = value.toInt();
		BFont* font = style_member(style)->valueMap[Value_Font];
		if (font == 0)
		{
			font = new BFont(app_font.ref());
			style_member(style)->valueMap[Value_Font] = font;
		}
		font->setSize(size);
		return;
	}
	if (sign == "font-tab" || sign == "font-tabsize")
	{
		int tabSize = value.toInt();
		if (tabSize < 1 || tabSize > 16)
		{
			errorMessage() << "" << sign << " should be in 1~16.";
			tabSize = bClamp(tabSize, 1, 16);
		}
		if (tabSize % 2)
		{
			errorMessage() << "" << sign << " should be even number (eg: 2, 4, ... 16).";
		}
		BFont* font = style_member(style)->valueMap[Value_Font];
		if (font == 0)
		{
			font = new BFont(app_font.ref());
			style_member(style)->valueMap[Value_Font] = font;
		}
		font->setTabSize(tabSize);
		return;
	}
	if (sign == "font-mono" || sign == "font-monospace")
	{
		bool monospace = ((value == "true") || (value == "on"));
		BFont* font = style_member(style)->valueMap[Value_Font];
		if (font == 0)
		{
			font = new BFont(app_font.ref());
			style_member(style)->valueMap[Value_Font] = font;
		}
		font->setMonospace(monospace);
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisArea(BStyle* style, BString& sign, BString& value)
{
	if (sign == "area-policy")
	{
		if (value.contain(','))
		{
			value.compact();
			BStringArray words;
			if (2 == value.split(words, ','))
			{
				style_member(style)->setPolicyValue(Value_Area_Width_Policy, words[0]);
				style_member(style)->setPolicyValue(Value_Area_Height_Policy, words[1]);
			}
		}
		style_member(style)->setPolicyValue(Value_Area_Width_Policy, value);
		style_member(style)->setPolicyValue(Value_Area_Height_Policy, value);
		return;
	}
	if (sign == "area-width-policy")
	{
		style_member(style)->setPolicyValue(Value_Area_Width_Policy, value);
		return;
	}
	if (sign == "area-height-policy")
	{
		style_member(style)->setPolicyValue(Value_Area_Height_Policy, value);
		return;
	}
	if (sign == "area-color")
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Area, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Area, state, color);
		}
		return;
	}
	if (sign == "area-image")
	{
		if (BImage* image = this->readImage(value))
		{
			State state = StringToState(sign);
			style->setImage(Image_Area, state, image);
		}
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisScroll(BStyle* style, BString& sign, BString& value)
{
	if (sign == "scroll-step")
	{
		style_member(style)->setScrollStep(Value_Scroll_Step, value);
		return;
	}
	if (sign == "scroll-hint")
	{
		style_member(style)->setScrollHint(Value_Scroll_Hor_Hint, value);
		style_member(style)->setScrollHint(Value_Scroll_Ver_Hint, value);
		return;
	}
	if (sign == "scroll-hint-hor" || sign == "scroll-hor-hint")
	{
		style_member(style)->setScrollHint(Value_Scroll_Hor_Hint, value);
		return;
	}
	if (sign == "scroll-hint-ver" || sign == "scroll-ver-hint")
	{
		style_member(style)->setScrollHint(Value_Scroll_Ver_Hint, value);
		return;
	}
}
void member_BStyleDocument::analysisSpread(BStyle* style, BString& sign, BString& value)
{
	if (sign == "spread" || sign == "spread-size")
	{
		if (!style_member(style)->setSizeValue(Value_Spread_Size, value))
			errorMessage() << "" << value << " : invalid size desc.";
		return;
	}
	if (sign == "spread-width")
	{
		BSize& size = style_member(style)->valueMap[Value_Spread_Size].fill<BSize>();
		size.width() = value.toInt();
		return;
	}
	if (sign == "spread-height")
	{
		BSize& size = style_member(style)->valueMap[Value_Spread_Size].fill<BSize>();
		size.height() = value.toInt();
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisChunk(BStyle* style, BString& sign, BString& value)
{
	if (sign == "chunk-size")
	{
		style_member(style)->setSizeValue(Value_Chunk_Size, value);
		return;
	}
	if (sign.beginWith("chunk-color"))
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Chunk, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Chunk, state, color);
		}
		return;
	}
	if (sign.beginWith("chunk-image"))
	{
		if (assignMultiImage(style, Image_Chunk, value))
			return;
		BImage* image = this->readImage(value);
		if (!image)
			return;
		State state = StringToState(sign);
		style->setImage(Image_Chunk, state, image);
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}

void member_BStyleDocument::analysisGroove(BStyle* style, BString& sign, BString& value)
{
	if (sign == "groove-size")
	{
		if (!style_member(style)->setIntValue(Value_Groove_Size, value))
			errorMessage() << "invalid value for groove size : " << value;
		return;
	}
	if (sign == "groove-color")
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Groove, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Groove, state, color);
		}
		return;
	}
	if (sign == "groove-image")
	{
		if (BImage* image = this->readImage(value))
			style_member(style)->imageMap[Image_Groove] = image;
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisIcon(BStyle* style, BString& sign, BString& value)
{
	if (sign == "icon")
	{
		if (BIcon* icon = this->readIcon(value))
			style_member(style)->valueMap[Value_Icon] = icon;
		return;
	}
	if (sign == "icon-size")
	{
		int w = value.toInt();
		BSize size(w, w);
		int comma_pos = value.find(',');
		value.remove(0, comma_pos + 1);
		value.trimmed();
		if (value.size())
		{
			size.height() = value.toInt();
		}
		style_member(style)->valueMap[Value_Icon_Size] = size;
		return;
	}
	if (sign == "icon-expand")
	{
		if (BIcon* icon = this->readIcon(value))
			style_member(style)->iconMap[Icon_Expand] = icon;
		return;
	}
	if (sign == "icon-shrink")
	{
		if (BIcon* icon = this->readIcon(value))
			style_member(style)->iconMap[Icon_Shrink] = icon;
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisImage(BStyle* style, BString& sign, BString& value)
{
	if (sign == "image")
	{
		if (BImage* image = this->readImage(value))
			style_member(style)->valueMap[Value_Image] = image;
		return;
	}
	if (sign == "image-size")
	{
		int w = value.toInt();
		BSize size(w, w);
		int comma_pos = value.find(',');
		value.remove(0, comma_pos + 1);
		value.trimmed();
		if (value.size())
		{
			size.height() = value.toInt();
		}
		style_member(style)->valueMap[Value_Image_Size] = size;
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisFixed(BStyle* style, BString& sign, BString& value)
{
	if (sign == "fixed-size")
	{
		if (value.contain(','))
		{
			BStringArray words = value.split(',');
			if (!style_member(style)->setIntValue(Value_Fixed_Width, words[0]))
				errorMessage() << "invalid fixed-width value : " << value;
			if (!style_member(style)->setIntValue(Value_Fixed_Height, words[1]))
				errorMessage() << "invalid fixed-height value : " << value;
		}
		else
		{
			if (!style_member(style)->setIntValue(Value_Fixed_Width, value))
				errorMessage() << "invalid fixed-width value : " << value;
			if (!style_member(style)->setIntValue(Value_Fixed_Height, value))
				errorMessage() << "invalid fixed-height value : " << value;
		}
		return;
	}
	if (sign == "fixed-width")
	{
		if (!style_member(style)->setIntValue(Value_Fixed_Width, value))
			errorMessage() << "invalid fixed-width value : " << value;
		return;
	}
	if (sign == "fixed-height")
	{
		if (!style_member(style)->setIntValue(Value_Fixed_Height, value))
			errorMessage() << "invalid fixed-height value : " << value;
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisMin(BStyle* style, BString& sign, BString& value)
{
	if (sign == "min-size")
	{
		if (value.contain(','))
		{
			BStringArray words = value.split(',');
			if (!style_member(style)->setIntValue(Value_Min_Width, words[0]))
				errorMessage() << "invalid min-width value : " << value;
			if (!style_member(style)->setIntValue(Value_Min_Height, words[1]))
				errorMessage() << "invalid min-height value : " << value;
		}
		else
		{
			if (!style_member(style)->setIntValue(Value_Min_Width, value))
				errorMessage() << "invalid min-width value : " << value;
			if (!style_member(style)->setIntValue(Value_Min_Height, value))
				errorMessage() << "invalid min-height value : " << value;
		}
		return;
	}
	if (sign == "min-width")
	{
		if (!style_member(style)->setIntValue(Value_Min_Width, value))
			errorMessage() << "invalid min-width value : " << value;
		return;
	}
	if (sign == "min-height")
	{
		if (!style_member(style)->setIntValue(Value_Min_Height, value))
			errorMessage() << "invalid min-height value : " << value;
		return;
	}

}
void member_BStyleDocument::analysisMax(BStyle* style, BString& sign, BString& value)
{
	if (sign == "max-size")
	{
		if (value.contain(','))
		{
			BStringArray words = value.split(',');
			if (!style_member(style)->setIntValue(Value_Max_Width, words[0]))
				errorMessage() << "invalid max-width value : " << value;
			if (!style_member(style)->setIntValue(Value_Max_Height, words[1]))
				errorMessage() << "invalid max-height value : " << value;
		}
		else
		{
			if (!style_member(style)->setIntValue(Value_Max_Width, value))
				errorMessage() << "invalid max-width value : " << value;
			if (!style_member(style)->setIntValue(Value_Max_Height, value))
				errorMessage() << "invalid max-height value : " << value;
		}
		return;
	}
	if (sign == "max-width")
	{
		if (!style_member(style)->setIntValue(Value_Max_Width, value))
			errorMessage() << "invalid max-width value : " << value;
		return;
	}
	if (sign == "max-height")
	{
		if (!style_member(style)->setIntValue(Value_Max_Height, value))
			errorMessage() << "invalid max-height value : " << value;
		return;
	}
}
void member_BStyleDocument::analysisArrow(BStyle* style, BString& sign, BString& value)
{
	if (sign == "arrow-size")
	{
		if (!style_member(style)->setSizeValue(Value_Arrow_Size, value))
			errorMessage() << "invalid size value : " << value;
		return;
	}

	if (sign == "arrow-part")
	{
		if (!style_member(style)->setPartValue(Value_Arrow_Part, value))
			errorMessage() << "invalid part value : " << value;
		return;
	}
	if (sign == "arrow-align")
	{
		if (!style_member(style)->setAlignValue(Value_Arrow_Align, value))
			errorMessage() << "invalid align value : " << value;
		return;
	}

	if (sign.beginWith("arrow-color"))
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Arrow, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Arrow, state, color);
		}
		return;
	}

	if (sign == "arrow-graph")
	{
		style_member(style)->setGraphValue(Value_Arrow_Graph, value);
		return;
	}

	if (sign.beginWith("arrow-icon"))
	{
		BIcon* icon = this->readIcon(value);
		if (!icon)
			return;
		if (sign == "arrow-icon")
		{
			style_member(style)->iconMap[Icon_Arrow_Up] = icon;
			style_member(style)->iconMap[Icon_Arrow_Down] = icon;
			style_member(style)->iconMap[Icon_Arrow_Left] = icon;
			style_member(style)->iconMap[Icon_Arrow_Right] = icon;
			return;
		}
		if (sign == "arrow-icon-up" || sign == "arrow-up-icon")
		{
			style_member(style)->iconMap[Icon_Arrow_Up] = icon;
			return;
		}
		if (sign == "arrow-icon-down" || sign == "arrow-down-icon")
		{
			style_member(style)->iconMap[Icon_Arrow_Down] = icon;
			return;
		}
		if (sign == "arrow-icon-left" || sign == "arrow-left-icon")
		{
			style_member(style)->iconMap[Icon_Arrow_Left] = icon;
			return;
		}
		if (sign == "arrow-icon-right" || sign == "arrow-right-icon")
		{
			style_member(style)->iconMap[Icon_Arrow_Right] = icon;
			return;
		}
		errorMessage() << "unknown sign : " << sign;
		return;
	}

	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisHandle(BStyle* style, BString& sign, BString& value)
{
	if (sign == "handle" || sign == "handle-size")
	{
		style_member(style)->setSizeValue(Value_Handle_Size, value);
		return;
	}
	if (sign == "handle-width")
	{
		BSize& size = style_member(style)->valueMap[Value_Handle_Size].fill<BSize>();
		size.width() = value.toInt();
		return;
	}
	if (sign == "handle-height")
	{
		BSize& size = style_member(style)->valueMap[Value_Handle_Size].fill<BSize>();
		size.height() = value.toInt();
		return;
	}
	if (sign.beginWith("handle-color"))
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Handle, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Handle, state, color);
		}
		return;
	}
	if (sign.beginWith("handle-image"))
	{
		if (assignMultiImage(style, Image_Handle, value))
			return;
		BImage* image = this->readImage(value);
		if (!image)
			return;
		State state = StringToState(sign);
		style->setImage(Image_Handle, state, image);
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisWire(BStyle* style, BString& sign, BString& value)
{
	if (sign == "wire")
	{
		if (!style_member(style)->setFloatValue(Value_Wire_Size, value))
			errorMessage() << "invalid wire size value : " << sign;
		return;
	}
	if (sign == "wire-stripe")
	{
		if (!style_member(style)->setWordValue(Value_Wire_Stripe, value))
			errorMessage() << "invalid wire stripe value : " << sign;
		return;
	}
	if (sign == "wire-size" || sign == "wire-width")
	{
		if (!style_member(style)->setFloatValue(Value_Wire_Size, value))
			errorMessage() << "invalid wire size value : " << sign;
		return;
	}
	if (sign.beginWith("wire-color"))
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Wire, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Wire, state, color);
		}
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisSelection(BStyle* style, BString& sign, BString& value)
{
	if (sign == "selection-color")
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Selection, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Selection, state, color);
		}
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisIndicator(BStyle* style, BString& sign, BString& value)
{
	if (sign == "indicator-color")
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Indicator, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Indicator, state, color);
		}
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisGridLine(BStyle* style, BString& sign, BString& value)
{
	if (sign == "grid" || sign == "grid-style")
	{
		GridStyle gridStyle = Grid_None;
		if (value == "vertical")
			gridStyle = Grid_Vertical;
		if (value == "horizontal")
			gridStyle = Grid_Horizontal;
		if (value == "crossing")
			gridStyle = Grid_Crossing;
		style_member(style)->valueMap[Value_Grid_Style] = gridStyle;
		return;
	}
	if (sign == "grid-style")
	{
		if(!style_member(style)->setGridStyle(Value_Grid_Style, value))
			errorMessage() << "invalid grid style value : " << value;
		return;
	}
	if (sign == "grid-size" || sign == "grid-width")
	{
		if (!style_member(style)->setIntValue(Value_Grid_Size, value))
			errorMessage() << "invalid grid size value : " << value;
		return;
	}
	if (sign == "grid-color")
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Grid_Hor, state);
			style->removeColor(Color_Grid_Ver, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Grid_Hor, state, color);
			style->setColor(Color_Grid_Ver, state, color);
		}
		return;
	}
	if (sign == "grid-color-ver" || sign == "grid-ver-color")
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Grid_Ver, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Grid_Ver, state, color);
		}
		return;
	}
	if (sign == "grid-color-hor" || sign == "grid-hor-color")
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Grid_Hor, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Grid_Hor, state, color);
		}
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}
void member_BStyleDocument::analysisLine(BStyle* style, BString& sign, BString& value)
{
	if (sign == "line-width")
	{
		if (!style_member(style)->setFloatValue(Value_Line_Width, value))
			errorMessage() << "invalid line width value : " << value;
		return;
	}
	if (sign == "line-height")
	{
		if (!style_member(style)->setIntValue(Value_Line_Height, value))
			errorMessage() << "invalid line height value : " << value;
		return;
	}
	if (sign == "line-spacing")
	{
		if (!style_member(style)->setIntValue(Value_Line_Spacing, value))
			errorMessage() << "invalid line spacing value : " << value;
		return;
	}
	if (sign.beginWith("line-color"))
	{
		State state = StringToState(sign);
		if (value == "unset")
		{
			style->removeColor(Color_Line, state);
			return;
		}
		BColor color;
		if (readColor(value, color))
		{
			style->setColor(Color_Line, state, color);
		}
		return;
	}
	errorMessage() << "unknown sign : " << sign;
}

void member_BStyleDocument::resourceValue(BStyle* style, BString& sign, BString& value)
{
	int sem_pos = value.find(':');
	if (sem_pos < value.size())
	{
		BString name;
		value.substr(name, 0, sem_pos);
		name.trimmed();
		if (name.empty())
		{
			errorMessage() << "name of value is empty : " << value;
			return;
		}
		value.remove(0, sem_pos + 1);
		value.trimmed();
		if (style_member(style)->namedValueMap.contain(name))
		{
			warningMessage() << "redefine value[" << name << "] " << value;
		}
		if (!style_member(style)->setMetaValue(name, value))
		{
			errorMessage() << "" << value << " : invalid value desc.";
		}
	}
}
void member_BStyleDocument::resourceColor(BStyle* style, BString& sign, BString& value)
{
	int sem_pos = value.find(':');
	if (sem_pos < value.size())
	{
		BString name;
		value.substr(name, 0, sem_pos);
		name.trimmed();
		if (name.empty())
		{
			errorMessage() << "name of color is empty : " << value;
			return;
		}
		value.remove(0, sem_pos + 1);
		value.trimmed();
		if (style_member(style)->namedColorMap.contain(name))
		{
			warningMessage() << "redefine color[" << name << "] " << value;
		}
		BColor color;
		if (readColor(value, color))
		{
			style_member(style)->namedColorMap[name] = color;
		}
	}
}
void member_BStyleDocument::resourceImage(BStyle* style, BString& sign, BString& value)
{
	int sem_pos = value.find(':');
	if (sem_pos < value.size())
	{
		BString name;
		value.substr(name, 0, sem_pos);
		name.trimmed();
		if (name.empty())
		{
			errorMessage() << "name of image is empty : " << value;
			return;
		}
		value.remove(0, sem_pos + 1);
		value.trimmed();
		if (value.beginWith("./"))
			value.remove(0, 2);
		BImage* image = this->readImage(value);
		if (!image)
			return;
		if (style_member(style)->namedImageMap.contain(name))
			warningMessage() << "redefine image [" << name << "] " << value;
		style_member(style)->namedImageMap[name] = image;
	}
}
void member_BStyleDocument::resourceIcon(BStyle* style, BString& sign, BString& value)
{
	int sem_pos = value.find(':');
	if (sem_pos < value.size())
	{
		BString name;
		value.substr(name, 0, sem_pos);
		name.trimmed();
		if (name.empty())
		{
			errorMessage() << "name of icon is empty : " << value;
			return;
		}
		if (style_member(style)->namedIconMap.contain(name))
		{
			warningMessage() << "redefine icon [" << name << "] " << value;
			return;
		}
		value.remove(0, sem_pos + 1);
		value.trimmed();
		if (value.beginWith("./"))
			value.remove(0, 2);
		if (BIcon* icon = this->readIcon(value))
			style_member(style)->namedIconMap[name] = icon;
	}
}
void member_BStyleDocument::resourceText(BStyle* style, BString& sign, BString& value)
{
	int sem_pos = 0;
	while (sem_pos < value.size())
	{
		if (value[sem_pos] == '\\')
		{
			value.remove(sem_pos);
			char next = value[sem_pos];
			if (next == 't')
				value[sem_pos] = '\t';
			if (next == 'n')
				value[sem_pos] = '\n';
			sem_pos++;
			continue;
		}
		if (value[sem_pos] == ':')
			break;
		sem_pos++;
	}
	if (sem_pos < value.size())
	{
		BString name;
		value.substr(name, 0, sem_pos);
		value.remove(0, sem_pos + 1);
		name.trimmed();
		name.lower();
		name.replace("\\:", ':');
		name.replace("\\s", ' ');
		name.replace("\\t", '\t');
		name.replace("\\n", '\n');
		value.trimmed();
		value.replace("\\:", ':');
		value.replace("\\s", ' ');
		value.replace("\\t", '\t');
		value.replace("\\n", '\n');
		if (name.size() && value.size())
		{
			if (style_member(style)->textMap.contain(name))
			{
				warningMessage() << "redefine text [" << name << "] " << value;
			}
			style_member(style)->textMap[name] = value;
		}
	}
	else
	{
		errorMessage() << "invalid text : " << value;
	}
}
void member_BStyleDocument::resourceWord(BStyle* style, BString& sign, BString& value)
{
	int sem_pos = 0;
	while (sem_pos < value.size())
	{
		if (value[sem_pos] == '\\')
		{
			value.remove(sem_pos);
			char n = value[sem_pos];
			if (n == 't')
				value[sem_pos] = '\t';
			if (n == 'n')
				value[sem_pos] = '\n';
			sem_pos++;
			continue;
		}
		if (value[sem_pos] == ':')
			break;
		sem_pos++;
	}
	if (sem_pos < value.size())
	{
		BString name;
		value.substr(name, 0, sem_pos);
		value.remove(0, sem_pos + 1);
		name.trimmed();
		name.lower();
		name.replace("\\:", ':');
		name.replace("\\s", ' ');
		name.replace("\\t", '\t');
		name.replace("\\n", '\n');
		value.trimmed();
		value.replace("\\:", ':');
		value.replace("\\s", ' ');
		value.replace("\\t", '\t');
		value.replace("\\n", '\n');
		if (name.size() && value.size())
		{
			if (style_member(style)->wordMap.contain(name))
			{
				warningMessage() << "redefine word [" << name << "] " << value;
			}
			style_member(style)->wordMap[name] = value;
		}
	}
	else
	{
		errorMessage() << "invalid word." << value;
	}
}
void member_BStyleDocument::resourceTrans(BStyle* style, BString& sign, BString& value)
{
	int sem_pos = 0;
	while (sem_pos < value.size())
	{
		if (value[sem_pos] == '\\' && value[sem_pos + 1] == ':')
		{
			sem_pos += 2;
			continue;
		}
		if (value[sem_pos] == ':')
			break;
		sem_pos++;
	}
	if (sem_pos < value.size())
	{
		BString name;
		value.substr(name, 0, sem_pos);
		value.remove(0, sem_pos + 1);
		name.trimmed();
		name.lower();
		name.replace("\\:", ':');
		name.replace("\\s", ' ');
		name.replace("\\t", '\t');
		name.replace("\\n", '\n');
		value.trimmed();
		value.replace("\\:", ':');
		value.replace("\\s", ' ');
		value.replace("\\t", '\t');
		value.replace("\\n", '\n');
		if (name.size() && value.size())
		{
			if (style_member(style)->transMap.contain(name))
			{
				warningMessage() << "redefine trans (" << name << ") " << value;
			}
			style_member(style)->transMap[name] = value;
		}
	}
	else
	{
		errorMessage() << "invalid text : " << value;
	}
}

bool member_BStyleDocument::readColor(BString& value, BColor& color)
{
	value.trimmed();
	if (value.empty())
		return false;
	color.a() = 255;
	bool result = false;
	if (value == "none" || value == "empty")
	{
		color.set(0, 0, 0, 0);
		result = true;
	}
	else if (value.beginWith('#'))
	{
		if (value.size() == 7)
		{
			color.r() = bHexToByte(value.cstr() + 1);
			color.g() = bHexToByte(value.cstr() + 3);
			color.b() = bHexToByte(value.cstr() + 5);
			color.a() = 255;
			result = true;
		}
		if (value.size() == 9)
		{
			color.r() = bHexToByte(value.cstr() + 1);
			color.g() = bHexToByte(value.cstr() + 3);
			color.b() = bHexToByte(value.cstr() + 5);
			color.a() = bHexToByte(value.cstr() + 7);
			result = true;
		}
	}
	else if (value.beginWith("rgb("))
	{
		int begin = value.find('(');
		int end = value.find(')');
		int index = 0;
		int pos = begin + 1;
		while (pos < end)
		{
			pos = value.word(colorStr, pos);
			if (colorStr == ',')
				index++;
			else if (colorStr.isNumber())
				color[index] = colorStr.toInt();
			else
				break;
		}
		result = (index == 2);
	}
	else if (value.beginWith("rgba("))
	{
		int begin = value.find('(');
		int end = value.find(')');
		int index = 0;
		int pos = begin + 1;
		while (pos < end)
		{
			pos = value.word(colorStr, pos);
			if (colorStr == ',')
				index++;
			else if (colorStr.isNumber())
				color[index] = colorStr.toInt();
			else
				break;
		}
		result = (index == 3);
	}
	else if (value.contain(','))
	{
		int index = 0;
		int pos = 0;
		while (pos < value.size())
		{
			pos = value.word(colorStr, pos);
			if (colorStr == ',')
				index++;
			else if (colorStr.isNumber())
				color[index] = colorStr.toInt();
			else
				break;
		}
		result = (index == 2) || (index == 3);
	}
	else
	{
		colorStr = value;
		colorStr.lower();
		color = BSystem::NamedColor(colorStr);
		result = color.a();
	}
	if (!result)
		errorMessage() << "" << value << " : invalid color desc.";
	return result;
}
bool member_BStyleDocument::assignMultiImage(BStyle* style, StyleImage name, const BString& fileName)
{
	BMap<State, BImageHolder> imageMap;
	readMultiImage(fileName, imageMap);
	if (imageMap.empty())
		return false;
	for (auto it = imageMap.begin(); it.valid(); ++it)
	{
		State state = it.key();
		BImage* image = it.value();
		style->setImage(name, state, image);
	}
	return true;
}
bool member_BStyleDocument::readMultiImage(const BString& fileName, BMap<State, BImageHolder>& imageMap)
{
	if (fileName.ext())
		return false;

	int split = fileName.find('|');
	if (split < fileName.size())
	{
		BString temp;
		fileName.substr(temp, 0, split);
		temp.trimmed();
		BImage* image = readImage(temp);
		if (!image)
			return false;

		BString splitText;
		fileName.substr(splitText, split + 1);
		int end = splitText.find(',');
		splitText.substr(temp, 0, end);

		temp.lower();
		int row = 0;
		int column = 0;
		BStringArray words;
		temp.split(words, '*');
		if (words.size() != 2 || !words[0].isNumber() || !words[1].isNumber())
		{
			errorMessage() << "split info is invalid : " << temp;
			return false;
		}
		row = words[0].toInt();
		column = words[1].toInt();

		splitText.truncate(end + 1);
		splitText.split(words, ',');
		if (words.empty())
		{
			errorMessage() << "load icon failed, (too less states) : " << fileName;
			return false;
		}

		BTable<BImageHolder> imageTable(row, column);
		SplitImage(image, imageTable);
		for (int i = 0; i < words.size(); i++)
		{
			BString word = words[i];
			word.trimmed();
			if (word.empty())
				continue;
			word.prepend('-');
			State state = StringToState(word);
			BImage* image = 0;
			int colon_pos = word.find(':');
			if (colon_pos == word.size())
			{
				image = imageTable.at(i);
			}
			else
			{
				temp.reset();
				temp.append(word, 0, colon_pos);
				temp.trimmed();
				state = StringToState(temp);
				word.remove(0, colon_pos + 1);
				int split = word.find('*');
				if (split < word.size())
				{
					int row = word.toInt();
					word.remove(0, split + 1);
					int column = word.toInt();
					image = imageTable.at(row - 1, column - 1);
				}
				else
				{
					int index = word.toInt();
					image = imageTable.at(index - 1);
				}
			}
			if (state == State_Max)
			{
				errorMessage() << "split image failed, bad state : " << words[i];
				return false;
			}
			if (image == 0)
			{
				errorMessage() << "split image failed, bad index : " << words[i];
				return false;
			}
			imageMap[state] = image;
		}
	}
	else
	{
		const char* name = fileName.name();
		BString filePath = fileName.path();
		BFolder folder(filePath);
		if (!folder.open() && path.size())
		{
			if (filePath.size())
			{
				filePath.reset();
				filePath << path << '/' << fileName.path();
				folder.setPath(filePath);
			}
			else
			{
				folder.setPath(path);
			}
			folder.open();
		}
		if (folder.isOpened())
		{
			for (int i = 0; i < folder.entryCount(); i++)
			{
				BEntry* entry = folder.entry(i);
				if (!(entry->attrib() & Attrib_File))
					continue;
				if (!entry->name().beginWith(name) || !entry->name().ext())
					continue;
				State state = StringToState(entry->name());
				imageMap[state] = ReadFile<BImage>(entry->path());
			}
		}
		else
		{
			filePath = fileName;
			auto begin = app_resources >= filePath;
			auto end = app_resources <= filePath + '~';
			if (begin >= end && path.size())
			{
				filePath.reset();
				filePath << path << '/' << fileName;
				begin = app_resources >= filePath;
				end = app_resources <= filePath + '~';
			}
			BString temp;
			for (auto it = begin; it <= end; ++it)
			{
				temp.reset();
				temp << it.key();
				temp.remove(filePath);
				if (temp.contain('/'))
					continue;
				if (!temp.ext())
					continue;
				State state = StringToState(temp);
				if (state == State_None && !temp.beginWith('.'))
					continue;
				imageMap[state] = ReadFile<BImage>(it.key());
			}
		}
	}

	if (imageMap.empty())
		return false;

	InitImageMap(imageMap);

	return true;
}
BImage* member_BStyleDocument::readImage(const BString& fileName)
{
	if (fileName == "none" || fileName == "empty")
		return 0;
	BImage* image = imageMap(fileName);
	if (!image)
	{
		BObject* obj = ReadFile(fileName);
		image = dynamic_cast<BImage*>(obj);
		if (obj && !image)
			delete obj;
	}
	if (!image && path.size())
	{
		BString filePath;
		filePath << path << '/' << fileName;
		BObject* obj = ReadFile(filePath);
		image = dynamic_cast<BImage*>(obj);
		if (obj && !image)
			delete obj;
	}
	if (image)
		imageMap[fileName] = image;
	else
		errorMessage() << "can't read image : " << fileName;
	return image;
}
BIcon* member_BStyleDocument::readIcon(const BString& fileName)
{
	if (fileName.ext())
	{
		if (BImage* image = readImage(fileName))
		{
			BIcon* icon = new BIcon(image);
			return icon;
		}
		return 0;
	}
	else
	{
		BMap<State, BImageHolder> imageMap;
		readMultiImage(fileName, imageMap);
		if (imageMap.size())
		{
			BIcon* icon = new BIcon();
			for (auto it = imageMap.begin(); it.valid(); ++it)
			{
				State state = it.key();
				BImage* image = it.value();
				icon_member(icon)->images[state] = image;
			}
			icon_member(icon)->fileName = fileName;
			return icon;
		}
	}
	//errorMessage() << "can't read icon : " << fileName;
	return 0;
}

void member_BStyleDocument::assemble(BString& text, int name, const BValue& value)
{
	switch (name)
	{
	case Value_Icon:	assembleIcon(text, "icon", value);		break;
	case Value_Image:	assembleImage(text, "image", value);	break;
	case Value_Graph:	assembleGraph(text, "graph", value);	break;
	case Value_Title:	assembleString(text, "title", value);	break;
	case Value_Width:	assembleInt(text, "width", value);		break;
	case Value_Height:	assembleInt(text, "height", value);		break;
	case Value_Form:	assembleForm(text, "form", value);		break;
	case Value_Align:	assembleAlign(text, "align", value);	break;
	case Value_Spacing:	assembleInt(text, "spacing", value);	break;
	case Value_Border:	assembleInt(text, "border", value);		break;
	case Value_Flat:	assembleBool(text, "flat", value);		break;
	case Value_Wired:	assembleBool(text, "wired", value);		break;

	case Value_Perch_Left:		assembleInt(text, "perch-left", value);		break;
	case Value_Perch_Right:		assembleInt(text, "perch-right", value);	break;
	case Value_Perch_Top:		assembleInt(text, "perch-top", value);		break;
	case Value_Perch_Bottom:	assembleInt(text, "perch-bottom", value);	break;

	case Value_Margin_Left:		assembleInt(text, "margin-left", value);	break;
	case Value_Margin_Right:	assembleInt(text, "margin-right", value);	break;
	case Value_Margin_Top:		assembleInt(text, "margin-top", value);		break;
	case Value_Margin_Bottom:	assembleInt(text, "margin-bottom", value);	break;

	case Value_Radius_Left_Top:		assembleSize(text, "radius-left-top", value);	break;
	case Value_Radius_Right_Top:	assembleSize(text, "radius-right-top", value);	break;
	case Value_Radius_Left_Bottom:	assembleSize(text, "radius-left-bottom", value); break;
	case Value_Radius_Right_Bottom:	assembleSize(text, "radius-right-bottom", value); break;

	case Value_Icon_Size:		assembleSize(text, "size", value);			break;
	case Value_Handle_Size:		assembleSize(text, "handle-size", value);	break;
	case Value_Wire_Size:		assembleFloat(text, "wire-size", value);		break;
	case Value_Grid_Style:		assmbleGridStyle(text, "grid-style", value); break;
	case Value_Groove_Size:		assembleInt(text, "groove-size", value);	break;

	case Value_Arrow_Size:		assembleSize(text, "arrow-size", value);	break;
	case Value_Arrow_Align:		assembleInt(text, "arrow-align", value);	break;

	default:
		break;
	}

	switch (name)
	{
	case Color_Title + State_Normal:			assembleColor(text, "title-color-normal", value);	break;
	case Color_Title + State_Normal_Hovered:	assembleColor(text, "title-color-normal-hovered", value);	break;
	case Color_Title + State_Normal_Pressed:	assembleColor(text, "title-color-normal-pressed", value);	break;
	case Color_Title + State_Normal_Selected:	assembleColor(text, "title-color-normal-selected", value);	break;

	case Color_Title + State_Actived:			assembleColor(text, "title-color-actived", value);	break;
	case Color_Title + State_Actived_Hovered:	assembleColor(text, "title-color-actived-hovered", value);	break;
	case Color_Title + State_Actived_Pressed:	assembleColor(text, "title-color-actived-pressed", value);	break;
	case Color_Title + State_Actived_Selected:	assembleColor(text, "title-color-actived-selected", value);	break;

	case Color_Title + State_Checked:			assembleColor(text, "title-color-checked", value);	break;
	case Color_Title + State_Checked_Hovered:	assembleColor(text, "title-color-checked-hovered", value);	break;
	case Color_Title + State_Checked_Pressed:	assembleColor(text, "title-color-checked-pressed", value);	break;
	case Color_Title + State_Checked_Selected:	assembleColor(text, "title-color-checked-selected", value);	break;

	case Color_Title + State_Disable:			assembleColor(text, "title-color-disable", value);	break;
	case Color_Title + State_Disable_Hovered:	assembleColor(text, "title-color-disable-hovered", value);	break;
	case Color_Title + State_Disable_Pressed:	assembleColor(text, "title-color-disable-pressed", value);	break;
	case Color_Title + State_Disable_Selected:	assembleColor(text, "title-color-disable-selected", value);	break;

	case Color_Text + State_Normal:				assembleColor(text, "text-color-normal", value);	break;
	case Color_Text + State_Normal_Hovered:		assembleColor(text, "text-color-normal-hovered", value);	break;
	case Color_Text + State_Normal_Pressed:		assembleColor(text, "text-color-normal-pressed", value);	break;
	case Color_Text + State_Normal_Selected:	assembleColor(text, "text-color-normal-selected", value);	break;

	case Color_Text + State_Actived:			assembleColor(text, "text-color-actived", value);	break;
	case Color_Text + State_Actived_Hovered:	assembleColor(text, "text-color-actived-hovered", value);	break;
	case Color_Text + State_Actived_Pressed:	assembleColor(text, "text-color-actived-pressed", value);	break;
	case Color_Text + State_Actived_Selected:	assembleColor(text, "text-color-actived-selected", value);	break;

	case Color_Text + State_Checked:			assembleColor(text, "text-color-checked", value);	break;
	case Color_Text + State_Checked_Hovered:	assembleColor(text, "text-color-checked-hovered", value);	break;
	case Color_Text + State_Checked_Pressed:	assembleColor(text, "text-color-checked-pressed", value);	break;
	case Color_Text + State_Checked_Selected:	assembleColor(text, "text-color-checked-selected", value);	break;

	case Color_Text + State_Disable:			assembleColor(text, "text-color-disable", value);	break;
	case Color_Text + State_Disable_Hovered:	assembleColor(text, "text-color-disable-hovered", value);	break;
	case Color_Text + State_Disable_Pressed:	assembleColor(text, "text-color-disable-pressed", value);	break;
	case Color_Text + State_Disable_Selected:	assembleColor(text, "text-color-disable-selected", value);	break;

	case Color_Background + State_Normal:			assembleColor(text, "background-color-normal", value);	break;
	case Color_Background + State_Normal_Hovered:	assembleColor(text, "background-color-normal-hovered", value);	break;
	case Color_Background + State_Normal_Pressed:	assembleColor(text, "background-color-normal-pressed", value);	break;
	case Color_Background + State_Normal_Selected:	assembleColor(text, "background-color-normal-selected", value);	break;

	case Color_Background + State_Actived:			assembleColor(text, "background-color-actived", value);	break;
	case Color_Background + State_Actived_Hovered:	assembleColor(text, "background-color-actived-hovered", value);	break;
	case Color_Background + State_Actived_Pressed:	assembleColor(text, "background-color-actived-pressed", value);	break;
	case Color_Background + State_Actived_Selected:	assembleColor(text, "background-color-actived-selected", value);	break;

	case Color_Background + State_Checked:			assembleColor(text, "background-color-checked", value);	break;
	case Color_Background + State_Checked_Hovered:	assembleColor(text, "background-color-checked-hovered", value);	break;
	case Color_Background + State_Checked_Pressed:	assembleColor(text, "background-color-checked-pressed", value);	break;
	case Color_Background + State_Checked_Selected:	assembleColor(text, "background-color-checked-selected", value);	break;

	case Color_Background + State_Disable:			assembleColor(text, "background-color-disable", value);	break;
	case Color_Background + State_Disable_Hovered:	assembleColor(text, "background-color-disable-hovered", value);	break;
	case Color_Background + State_Disable_Pressed:	assembleColor(text, "background-color-disable-pressed", value);	break;
	case Color_Background + State_Disable_Selected:	assembleColor(text, "background-color-disable-selected", value);	break;

	case Color_Border + State_Normal:			assembleColor(text, "border-color-normal", value);	break;
	case Color_Border + State_Normal_Hovered:	assembleColor(text, "border-color-normal-hovered", value);	break;
	case Color_Border + State_Normal_Pressed:	assembleColor(text, "border-color-normal-pressed", value);	break;
	case Color_Border + State_Normal_Selected:	assembleColor(text, "border-color-normal-selected", value);	break;

	case Color_Border + State_Actived:			assembleColor(text, "border-color-actived", value);	break;
	case Color_Border + State_Actived_Hovered:	assembleColor(text, "border-color-actived-hovered", value);	break;
	case Color_Border + State_Actived_Pressed:	assembleColor(text, "border-color-actived-pressed", value);	break;
	case Color_Border + State_Actived_Selected:	assembleColor(text, "border-color-actived-selected", value);	break;

	case Color_Border + State_Checked:			assembleColor(text, "border-color-checked", value);	break;
	case Color_Border + State_Checked_Hovered:	assembleColor(text, "border-color-checked-hovered", value);	break;
	case Color_Border + State_Checked_Pressed:	assembleColor(text, "border-color-checked-pressed", value);	break;
	case Color_Border + State_Checked_Selected:	assembleColor(text, "border-color-checked-selected", value);	break;

	case Color_Border + State_Disable:			assembleColor(text, "border-color-disable", value);	break;
	case Color_Border + State_Disable_Hovered:	assembleColor(text, "border-color-disable-hovered", value);	break;
	case Color_Border + State_Disable_Pressed:	assembleColor(text, "border-color-disable-pressed", value);	break;
	case Color_Border + State_Disable_Selected:	assembleColor(text, "border-color-disable-selected", value);	break;

	case Color_Perch + State_Normal:			assembleColor(text, "perch-color-normal", value);	break;
	case Color_Perch + State_Normal_Hovered:	assembleColor(text, "perch-color-normal-hovered", value);	break;
	case Color_Perch + State_Normal_Pressed:	assembleColor(text, "perch-color-normal-pressed", value);	break;
	case Color_Perch + State_Normal_Selected:	assembleColor(text, "perch-color-normal-selected", value);	break;

	case Color_Perch + State_Actived:			assembleColor(text, "perch-color-actived", value);	break;
	case Color_Perch + State_Actived_Hovered:	assembleColor(text, "perch-color-actived-hovered", value);	break;
	case Color_Perch + State_Actived_Pressed:	assembleColor(text, "perch-color-actived-pressed", value);	break;
	case Color_Perch + State_Actived_Selected:	assembleColor(text, "perch-color-actived-selected", value);	break;

	case Color_Perch + State_Checked:			assembleColor(text, "perch-color-checked", value);	break;
	case Color_Perch + State_Checked_Hovered:	assembleColor(text, "perch-color-checked-hovered", value);	break;
	case Color_Perch + State_Checked_Pressed:	assembleColor(text, "perch-color-checked-pressed", value);	break;
	case Color_Perch + State_Checked_Selected:	assembleColor(text, "perch-color-checked-selected", value);	break;

	case Color_Perch + State_Disable:			assembleColor(text, "perch-color-disable", value);	break;
	case Color_Perch + State_Disable_Hovered:	assembleColor(text, "perch-color-disable-hovered", value);	break;
	case Color_Perch + State_Disable_Pressed:	assembleColor(text, "perch-color-disable-pressed", value);	break;
	case Color_Perch + State_Disable_Selected:	assembleColor(text, "perch-color-disable-selected", value);	break;

	case Color_Margin + State_Normal:			assembleColor(text, "margin-color-normal", value);	break;
	case Color_Margin + State_Normal_Hovered:	assembleColor(text, "margin-color-normal-hovered", value);	break;
	case Color_Margin + State_Normal_Pressed:	assembleColor(text, "margin-color-normal-pressed", value);	break;
	case Color_Margin + State_Normal_Selected:	assembleColor(text, "margin-color-normal-selected", value);	break;

	case Color_Margin + State_Actived:			assembleColor(text, "margin-color-actived", value);	break;
	case Color_Margin + State_Actived_Hovered:	assembleColor(text, "margin-color-actived-hovered", value);	break;
	case Color_Margin + State_Actived_Pressed:	assembleColor(text, "margin-color-actived-pressed", value);	break;
	case Color_Margin + State_Actived_Selected:	assembleColor(text, "margin-color-actived-selected", value);	break;

	case Color_Margin + State_Checked:			assembleColor(text, "margin-color-checked", value);	break;
	case Color_Margin + State_Checked_Hovered:	assembleColor(text, "margin-color-checked-hovered", value);	break;
	case Color_Margin + State_Checked_Pressed:	assembleColor(text, "margin-color-checked-pressed", value);	break;
	case Color_Margin + State_Checked_Selected:	assembleColor(text, "margin-color-checked-selected", value);	break;

	case Color_Margin + State_Disable:			assembleColor(text, "margin-color-disable", value);	break;
	case Color_Margin + State_Disable_Hovered:	assembleColor(text, "margin-color-disable-hovered", value);	break;
	case Color_Margin + State_Disable_Pressed:	assembleColor(text, "margin-color-disable-pressed", value);	break;
	case Color_Margin + State_Disable_Selected:	assembleColor(text, "margin-color-disable-selected", value);	break;

	case Color_Handle + State_Normal:			assembleColor(text, "handle-color-normal", value);	break;
	case Color_Handle + State_Normal_Hovered:	assembleColor(text, "handle-color-normal-hovered", value);	break;
	case Color_Handle + State_Normal_Pressed:	assembleColor(text, "handle-color-normal-pressed", value);	break;
	case Color_Handle + State_Normal_Selected:	assembleColor(text, "handle-color-normal-selected", value);	break;

	case Color_Handle + State_Actived:			assembleColor(text, "handle-color-actived", value);	break;
	case Color_Handle + State_Actived_Hovered:	assembleColor(text, "handle-color-actived-hovered", value);	break;
	case Color_Handle + State_Actived_Pressed:	assembleColor(text, "handle-color-actived-pressed", value);	break;
	case Color_Handle + State_Actived_Selected:	assembleColor(text, "handle-color-actived-selected", value);	break;

	case Color_Handle + State_Checked:			assembleColor(text, "handle-color-checked", value);	break;
	case Color_Handle + State_Checked_Hovered:	assembleColor(text, "handle-color-checked-hovered", value);	break;
	case Color_Handle + State_Checked_Pressed:	assembleColor(text, "handle-color-checked-pressed", value);	break;
	case Color_Handle + State_Checked_Selected:	assembleColor(text, "handle-color-checked-selected", value);	break;

	case Color_Handle + State_Disable:			assembleColor(text, "handle-color-disable", value);	break;
	case Color_Handle + State_Disable_Hovered:	assembleColor(text, "handle-color-disable-hovered", value);	break;
	case Color_Handle + State_Disable_Pressed:	assembleColor(text, "handle-color-disable-pressed", value);	break;
	case Color_Handle + State_Disable_Selected:	assembleColor(text, "handle-color-disable-selected", value);	break;

	case Color_Arrow + State_Normal:			assembleColor(text, "arrow-color-normal", value);	break;
	case Color_Arrow + State_Normal_Hovered:	assembleColor(text, "arrow-color-normal-hovered", value);	break;
	case Color_Arrow + State_Normal_Pressed:	assembleColor(text, "arrow-color-normal-pressed", value);	break;
	case Color_Arrow + State_Normal_Selected:	assembleColor(text, "arrow-color-normal-selected", value);	break;

	case Color_Arrow + State_Actived:			assembleColor(text, "arrow-color-actived", value);	break;
	case Color_Arrow + State_Actived_Hovered:	assembleColor(text, "arrow-color-actived-hovered", value);	break;
	case Color_Arrow + State_Actived_Pressed:	assembleColor(text, "arrow-color-actived-pressed", value);	break;
	case Color_Arrow + State_Actived_Selected:	assembleColor(text, "arrow-color-actived-selected", value);	break;

	case Color_Arrow + State_Checked:			assembleColor(text, "arrow-color-checked", value);	break;
	case Color_Arrow + State_Checked_Hovered:	assembleColor(text, "arrow-color-checked-hovered", value);	break;
	case Color_Arrow + State_Checked_Pressed:	assembleColor(text, "arrow-color-checked-pressed", value);	break;
	case Color_Arrow + State_Checked_Selected:	assembleColor(text, "arrow-color-checked-selected", value);	break;

	case Color_Arrow + State_Disable:			assembleColor(text, "arrow-color-disable", value);	break;
	case Color_Arrow + State_Disable_Hovered:	assembleColor(text, "arrow-color-disable-hovered", value);	break;
	case Color_Arrow + State_Disable_Pressed:	assembleColor(text, "arrow-color-disable-pressed", value);	break;
	case Color_Arrow + State_Disable_Selected:	assembleColor(text, "arrow-color-disable-selected", value);	break;

	case Color_Wire:			assembleColor(text, "wire-color", value);		break;
	case Color_Chunk:			assembleColor(text, "chunk-color", value);		break;
	case Color_Groove:			assembleColor(text, "groove-color", value);		break;
	case Color_Separator:		assembleColor(text, "separator-color", value);	break;
	case Color_Indicator:		assembleColor(text, "indicator-color", value);	break;
	case Color_Grid_Ver:		assembleColor(text, "grid-ver-color", value);	break;
	case Color_Grid_Hor:		assembleColor(text, "grid-hor-color", value);	break;

	default:
		break;
	}

	switch (name)
	{
	case Image_Title + State_Normal:			assembleImage(text, "title-image-normal", value);	break;
	case Image_Title + State_Normal_Hovered:	assembleImage(text, "title-image-normal-hovered", value);	break;
	case Image_Title + State_Normal_Pressed:	assembleImage(text, "title-image-normal-pressed", value);	break;
	case Image_Title + State_Normal_Selected:	assembleImage(text, "title-image-normal-selected", value);	break;

	case Image_Title + State_Actived:			assembleImage(text, "title-image-actived", value);	break;
	case Image_Title + State_Actived_Hovered:	assembleImage(text, "title-image-actived-hovered", value);	break;
	case Image_Title + State_Actived_Pressed:	assembleImage(text, "title-image-actived-pressed", value);	break;
	case Image_Title + State_Actived_Selected:	assembleImage(text, "title-image-actived-selected", value);	break;

	case Image_Title + State_Checked:			assembleImage(text, "title-image-checked", value);	break;
	case Image_Title + State_Checked_Hovered:	assembleImage(text, "title-image-checked-hovered", value);	break;
	case Image_Title + State_Checked_Pressed:	assembleImage(text, "title-image-checked-pressed", value);	break;
	case Image_Title + State_Checked_Selected:	assembleImage(text, "title-image-checked-selected", value);	break;

	case Image_Title + State_Disable:			assembleImage(text, "title-image-disable", value);	break;
	case Image_Title + State_Disable_Hovered:	assembleImage(text, "title-image-disable-hovered", value);	break;
	case Image_Title + State_Disable_Pressed:	assembleImage(text, "title-image-disable-pressed", value);	break;
	case Image_Title + State_Disable_Selected:	assembleImage(text, "title-image-disable-selected", value);	break;

	case Image_Background + State_Normal:			assembleImage(text, "background-image-normal", value);	break;
	case Image_Background + State_Normal_Hovered:	assembleImage(text, "background-image-normal-hovered", value);	break;
	case Image_Background + State_Normal_Pressed:	assembleImage(text, "background-image-normal-pressed", value);	break;
	case Image_Background + State_Normal_Selected:	assembleImage(text, "background-image-normal-selected", value);	break;

	case Image_Background + State_Actived:			assembleImage(text, "background-image-actived", value);	break;
	case Image_Background + State_Actived_Hovered:	assembleImage(text, "background-image-actived-hovered", value);	break;
	case Image_Background + State_Actived_Pressed:	assembleImage(text, "background-image-actived-pressed", value);	break;
	case Image_Background + State_Actived_Selected:	assembleImage(text, "background-image-actived-selected", value);	break;

	case Image_Background + State_Checked:			assembleImage(text, "background-image-checked", value);	break;
	case Image_Background + State_Checked_Hovered:	assembleImage(text, "background-image-checked-hovered", value);	break;
	case Image_Background + State_Checked_Pressed:	assembleImage(text, "background-image-checked-pressed", value);	break;
	case Image_Background + State_Checked_Selected:	assembleImage(text, "background-image-checked-selected", value);	break;

	case Image_Background + State_Disable:			assembleImage(text, "background-image-disable", value);	break;
	case Image_Background + State_Disable_Hovered:	assembleImage(text, "background-image-disable-hovered", value);	break;
	case Image_Background + State_Disable_Pressed:	assembleImage(text, "background-image-disable-pressed", value);	break;
	case Image_Background + State_Disable_Selected:	assembleImage(text, "background-image-disable-selected", value);	break;

	case Image_Groove:		assembleImage(text, "groove-image", value);		break;

	default:
		break;
	}

	switch (name)
	{
	case Icon_Arrow_Up:		assembleImage(text, "arrow-icon-up", value);	break;
	case Icon_Arrow_Down:	assembleImage(text, "arrow-icon-down", value);	break;
	case Icon_Arrow_Left:	assembleImage(text, "arrow-icon-left", value);	break;
	case Icon_Arrow_Right:	assembleImage(text, "arrow-icon-right", value);	break;

	case Icon_Expand:		assembleImage(text, "expand-icon", value);		break;
	case Icon_Shrink:		assembleImage(text, "shrink-icon", value);		break;
	case Icon_About:		assembleImage(text, "about-icon", value);		break;
	case Icon_Information:	assembleImage(text, "information-icon", value);	break;
	case Icon_Question:		assembleImage(text, "question-icon", value);	break;
	case Icon_Warning:		assembleImage(text, "warning-icon", value);		break;
	case Icon_Critical:		assembleImage(text, "critical-icon", value);	break;

	default:
		break;
	}
}
void member_BStyleDocument::assembleString(BString& text, const char* sign, const BValue& value)
{
	if (!value.is<BString>())
	{
		errorMessage() << "[" << sign << "] : is not BString : ";
		return;
	}
	const BString& str = value;
	text << sign << ": " << str << ';';
}
void member_BStyleDocument::assembleBool(BString& text, const char* sign, const BValue& value)
{
	if (!value.is<bool>())
	{
		errorMessage() << "[" << sign << "] : is not bool : ";
		return;
	}
	bool b = value;
	text << sign << ": ";
	if (b)
		text << "true";
	else
		text << "false";
	text << ';';
}
void member_BStyleDocument::assembleInt(BString& text, const char* sign, const BValue& value)
{
	if (!value.is<int>())
	{
		errorMessage() << "[" << sign << "] : is not int : ";
		return;
	}
	int i = value;
	text << sign << ": " << i << ';';
}
void member_BStyleDocument::assembleFloat(BString& text, const char* sign, const BValue& value)
{
	if (!value.is<float>())
	{
		errorMessage() << "[" << sign << "] : is not float : ";
		return;
	}
	float f = value;
	text << sign << ": " << f << ';';
}
void member_BStyleDocument::assembleDouble(BString& text, const char* sign, const BValue& value)
{
	if (!value.is<double>())
	{
		errorMessage() << "[" << sign << "] : is not double : ";
		return;
	}
	double d = value;
	text << sign << ": " << d << ';';
}
void member_BStyleDocument::assembleSize(BString& text, const char* sign, const BValue& value)
{
	if (!value.is<BSize>())
	{
		errorMessage() << "[" << sign << "] : is not size : ";
		return;
	}
	const BSize& size = value;
	text << sign << ": " << size.width() << ", " << size.height() << ';';
}
void member_BStyleDocument::assembleIcon(BString& text, const char* sign, const BValue& value)
{
	if (!value.is<BIcon>())
	{
		errorMessage() << "[" << sign << "] : is not icon : ";
		return;
	}
	const BIcon* icon = value;
	text << sign << ": " << icon->name() << ';';
}
void member_BStyleDocument::assembleImage(BString& text, const char* sign, const BValue& value)
{
	if (!value.is<BImage>())
	{
		errorMessage() << "[" << sign << "] : is not image : ";
		return;
	}
	const BImage* image = value;
	text << sign << image->fileName() << ';';
}
void member_BStyleDocument::assembleColor(BString& text, const char* sign, const BValue& value)
{
	if (!value.is<BColor>())
	{
		errorMessage() << "[" << sign << "] : is not color : ";
		return;
	}
	const BColor& color = value;
	text << sign << ": " << color.r() << ", " << color.g() << ", " << color.b();
	if (color.a() < 255)
		text << ", " << color.a();
	text << ';';
}
void member_BStyleDocument::assmbleGridStyle(BString& text, const char* sign, const BValue& value)
{
	if (!value.is<GridStyle>())
	{
		errorMessage() << "[" << sign << "] : is not grid style : ";
		return;
	}
	text << sign << ": ";
	GridStyle gridStyle = value;
	switch (gridStyle)
	{
	case BWE::Grid_None:		text << "none";		break;
	case BWE::Grid_Vertical:	text << "vertical";		break;
	case BWE::Grid_Horizontal:	text << "horizontal";	break;
	case BWE::Grid_Crossing:	text << "crossing";		break;
	default:					text << "unknown";		break;
	}
	text << ';';
}
void member_BStyleDocument::assembleGraph(BString& text, const char* sign, const BValue& value)
{
	if (!value.is<Graph>())
	{
		errorMessage() << "[" << sign << "] : is not graph.";
		return;
	}
	text << sign << ": ";
	Graph graph = value;
	switch (graph)
	{
	case Graph_None:				text << "none";				break;
	case Graph_Circle:				text << "circle";			break;
	case Graph_Circle_Fill:			text << "circle-fill";		break;
	case Graph_Square:				text << "square";			break;
	case Graph_Square_Fill:			text << "square-fill";		break;
	case Graph_Arrow_Up:			text << "arrow-up";			break;
	case Graph_Arrow_Up_Fill:		text << "arrow-up-fill";	break;
	case Graph_Arrow_Down:			text << "arrow-down";		break;
	case Graph_Arrow_Down_Fill:		text << "arrow-down-fill";	break;
	case Graph_Arrow_Left:			text << "arrow-left";		break;
	case Graph_Arrow_Left_Fill:		text << "arrow-left-fill";	break;
	case Graph_Arrow_Right:			text << "arrow-right";		break;
	case Graph_Arrow_Right_Fill:	text << "arrow-right-fill";	break;
	case Graph_Plus:				text << "plus";				break;
	case Graph_Minus:				text << "minus";			break;
	case Graph_Cross:				text << "cross";			break;
	case Graph_Minimize:			text << "minimize";			break;
	case Graph_Maximize:			text << "maximize";			break;
	case Graph_Normalize:			text << "normalize";		break;
	default:						text << "unknown";			break;
	}
	text << ';';
}
void member_BStyleDocument::assembleForm(BString& text, const char* sign, const BValue& value)
{
	if (!value.is<Form>())
	{
		errorMessage() << "[" << sign << "] : is not graph.";
		return;
	}
	text << sign << ": ";
	Form form = value;
	switch (form)
	{
	case Form_None:				text << "none";				break;
	case Form_IconAlone:		text << "icon-alone";		break;
	case Form_TextAlone:		text << "text-alone";		break;
	case Form_TextOnly:			text << "text-only";		break;
	case Form_IconOnly:			text << "icon-only";		break;
	case Form_IconText:			text << "icon-text";		break;
	case Form_TextIcon:			text << "text-icon";		break;
	case Form_TextUnderIcon:	text << "text-under-icon";	break;
	case Form_IconUnderText:	text << "icon-under-text";	break;
	default:					text << "unknown";			break;
	}
	text << ';';
}
void member_BStyleDocument::assembleAlign(BString& text, const char* sign, const BValue& value)
{
	if (!value.is<Align>())
	{
		errorMessage() << "[" << sign << "] : is not align.";
		return;
	}
	text << sign << ": ";
	Align align = value;
	switch (align)
	{
	case Align_None:			text << "none";			break;
	case Align_Left:			text << "left";			break;
	case Align_Right:			text << "right";		break;
	case Align_HCenter:			text << "hcenter";		break;
	case Align_Top:				text << "top";			break;
	case Align_Bottom:			text << "bottom";		break;
	case Align_VCenter:			text << "vcenter";		break;
	case Align_LeftTop:			text << "left,top";		break;
	case Align_LeftCenter:		text << "left,center";	break;
	case Align_LeftBottom:		text << "left,bottom";	break;
	case Align_RightTop:		text << "right,top";	break;
	case Align_RightCenter:		text << "right,center";	break;
	case Align_RightBottom:		text << "right,bottom";	break;
	case Align_TopCenter:		text << "top,center";	break;
	case Align_BottomCenter:	text << "bottom,center"; break;
	case Align_Center:			text << "center";		break;
	default:					text << "unknown";		break;
	}
	text << ';';
}
